package cn.ggsaas.security.config;

import cn.ggsaas.security.handler.*;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 权限配置
 *
 * @author xuhongliang
 * @date 2020/9/14
 */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	private final UserDetailsService userDetailsService;

	@Bean("passwordEncoder")
	PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	public WebMvcConfigurer corsConfigurer() {
		return new WebMvcConfigurer() {
			@Override
			public void addCorsMappings(CorsRegistry registry) {
				registry.addMapping("/**")
					.allowedOrigins("*")
					.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
					.allowCredentials(true)
					.allowedHeaders("*");
			}
		};
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 开启跨域共享
		// 跨域伪造请求限制无效
		http.cors();
		http.csrf().disable();

		// 授权配置
		http.authorizeRequests()
			// 开启授权认证
			.anyRequest().authenticated();

		// UsernamePasswordAuthenticationFilter 登录配置
		http.formLogin().usernameParameter("username").passwordParameter("password")
			.loginProcessingUrl("/login");

		// 退出成功处理器，退出后 session 失效
		http.logout().logoutUrl("/logout").permitAll()
			.invalidateHttpSession(true).logoutSuccessHandler(new LogoutHandler());

		// 登录失败后 处理
		http.formLogin().failureHandler(new LoginFailureHandler());

		// 登录过期/未登录 处理
		http.exceptionHandling().authenticationEntryPoint(new LoginExpireHandler());

		// 权限不足 处理
		http.exceptionHandling().accessDeniedHandler(new AuthLimitHandler());

		// 登录成功后 处理
		http.formLogin().successHandler(new LoginSuccessHandler());
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}

	@Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
